package com.shuqi.download.core;

import java.net.HttpURLConnection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import com.shuqi.download.database.DownloadInfo;
import com.shuqi.download.database.DownloadInfoDao;
import com.shuqi.download.intf.FileThreadInterface;
import com.shuqi.download.listener.BlockStateListener;
import com.shuqi.download.util.Constant;
import com.shuqi.download.util.DownloadStatus;
import com.shuqi.download.util.Util;

/**
 * 文件下载线程
 * @author GaoPeng<gaopeng@ucweb.com>
 *
 */
public class FileThread implements Runnable,FileThreadInterface,BlockStateListener {
    
    // 用户ID
    private String uid;
    // 书籍ID
    private String bid;
    
    // 下载信息
    private DownloadInfo downloadInfo;
    
    // 线程池
    private ExecutorService pool=null;
    // 线程池大小（默认）
    private int poolSize=1;
    // 文件下载地址
    private String fileUrl;
    // 文件总字节数
    private int totalLength=0;
    
    // 按时间回传临时变量
    private long downTime=0;
    // 进度回传类型（默认为0，按百分比回传；1为按时间间隔回传）
    private int progressType=0;
    // 回传单位（默认为1，n/%或n毫秒）
    private int progressUnit=1;
    
    // 是否手动暂停
    private boolean isPaused=false;
    
    FileThread(String uid,String bid) {
        this.uid=uid;
        this.bid=bid;
        downloadInfo=new DownloadInfo();
        downloadInfo.setUserId(this.uid);
        downloadInfo.setBookId(this.bid);
    }
    
    /**
     * 初始化（必须）
     * @param fileUrl
     * @param poolSize
     * @param progressType
     * @param progressUnit
     */
    protected void init(String fileUrl,int poolSize,int progressType,int progressUnit) {
        this.fileUrl=fileUrl;
        // 如果是高速网络则用多线程
        if(Util.isHighNet()&&poolSize>0&&poolSize<=5) {
            this.poolSize=poolSize;
        }
        this.progressType=(progressType==1)?1:0;// 默认为0，按百分比回传
        if(this.progressType==0) {// 按百分比回传
            if(progressUnit>0&&progressUnit<=100) {
                this.progressUnit=progressUnit;
            }
        } else {// 按时间间隔回传
            if(progressUnit>=100&&progressUnit<=30000) {
                this.progressUnit=progressUnit;
            } else {
                this.progressUnit=1000;// 回传单位默认为1000毫秒
            }
        }
        pool = Executors.newFixedThreadPool(this.poolSize);
    }
    
    /**
     * 获取下载信息
     * @return
     */
    protected DownloadInfo getDownloadInfo() {
        return this.downloadInfo;
    }
    
    @Override
    public void run() {
        // 下载线程池不存在
        if(pool==null) {
            Util.log("下载线程池不存在（可能未调用init()方法进行初始化）");
        } else {
            // 记录开始时间
            long startTime=System.currentTimeMillis();
            Util.log("<<<运行文件下载线程（"+fileUrl+"）");
            HttpURLConnection conn=Util.getConnection(fileUrl, null, 1, 2);
            if(conn!=null) {
                try {
                    totalLength = conn.getContentLength();
                    Util.log("接收总数据大小（"+totalLength+"）");
                    if(totalLength<1) {
                        throw new Exception("接收数据大小异常");
                    }
                    String filePath=Constant.CACHE_PATH+"/"+Util.parseFileName(uid, bid);
                    // 获取下载线程列表
                    List<DownloadInfo> list=DownloadInfoDao.getInstance().getAllDownloadThreadInfo(uid, bid, fileUrl, totalLength, poolSize, filePath);
                    // 读取文件下载信息（恢复文件原下载状态）
                    downloadInfo=DownloadInfoDao.getInstance().getDownloadInfo(uid, bid);
                    if(downloadInfo!=null) {
                        try {
                            Util.log("已恢复文件原下载状态（"+downloadInfo+"）");
                            // 状态为等待或停止时运行线程
                            if(downloadInfo.getDownloadStatus()==DownloadStatus.STATE_WAIT
                                    ||downloadInfo.getDownloadStatus()==DownloadStatus.STATE_STOP) {
                                if(list!=null&&list.size()>0) {
                                    // 设置下载状态为开始下载
                                    downloadInfo.setDownloadStatus(DownloadStatus.STATE_RUN);
                                    for(DownloadInfo downloadInfo2:list) {
                                        // 执行未完成的线程
                                        if(downloadInfo2.getDownloadStatus()!=1) {
                                            Util.log("下载线程数据块（"+downloadInfo2.getPosStart()+"-"+downloadInfo2.getPosEnd()+"）");
                                            BlockThread thread=new BlockThread(this,downloadInfo2);
                                            pool.execute(thread);
                                        }
                                    }
                                }
                                // 关闭线程池（会等待已执行线程结束，但无法再提交新线程）
                                pool.shutdown();
                                // 等待子线程结束再执行后续代码（最大等待一天）
                                pool.awaitTermination(86400, TimeUnit.SECONDS);
                                Util.log("文件下载结束（已下载："+downloadInfo.getDownLength()+"，总大小："+totalLength+"，百分比："+downloadInfo.getDownloadPercent()+"）");
                                // 下载完成
                                if(downloadInfo.getDownLength()>=totalLength) {
                                    // 设置下载状态为正在解压
                                    downloadInfo.setDownloadStatus(DownloadStatus.STATE_UNZIP);
                                } else {
                                    // 下载未完成设置下载状态为停止下载
                                    downloadInfo.setDownloadStatus(DownloadStatus.STATE_STOP);
                                }
                            }
                            DownloadManager.getInstance().notifyDownloadState(uid,bid,downloadInfo.getDownloadStatus(),downloadInfo.getDownloadPercent());
                            // 解压文件
                            if(downloadInfo.getDownloadStatus()==DownloadStatus.STATE_UNZIP||downloadInfo.getDownloadStatus()==DownloadStatus.STATE_UNZIP_STOP) {
                                Util.log("开始解压文件");
                                if(Util.unzip(filePath, Constant.DOWNLOAD_PATH+"/"+uid+"/"+bid+"/", true, 2)) {
                                    Util.log("文件解压完成");
                                    // 进度设置为100%
                                    downloadInfo.setDownloadPercent(100);
                                    // 设置下载状态为完成下载
                                    downloadInfo.setDownloadStatus(DownloadStatus.STATE_DONE);
                                } else {
                                    Util.log("文件解压失败");
                                    // 设置下载状态为停止解压
                                    downloadInfo.setDownloadStatus(DownloadStatus.STATE_UNZIP_STOP);
                                }
                            }
                        } catch(Exception e) {
                            e.printStackTrace();
                        } finally {
                            // 如果不为手动暂停并且下载状态为暂停则给错误提示（代表未知异常发生）
                            if(!isPaused&&downloadInfo.getDownloadStatus()==DownloadStatus.STATE_STOP) {
                                DownloadManager.getInstance().notifyDownloadState(uid,bid,DownloadStatus.STATE_ERR_CONN,-1);
                            } else {// 正常提示
                                DownloadManager.getInstance().notifyDownloadState(uid,bid,downloadInfo.getDownloadStatus(),downloadInfo.getDownloadPercent());
                            }
                            // 将文件下载状态写入数据库
                            DownloadInfoDao.getInstance().update(downloadInfo);
                            Util.log("将文件下载状态写入数据库（"+downloadInfo+"）");
                        }
                    } else {
                        Util.log("读取文件下载信息为空（uid:"+uid+",bid:"+bid+"）");
                        DownloadManager.getInstance().notifyDownloadState(uid,bid,DownloadStatus.STATE_ERR_CONN,-1);
                    }
                } catch (Exception e) {
                    Util.log("下载文件发生异常（"+e.getMessage()+"）");
                    DownloadManager.getInstance().notifyDownloadState(uid,bid,DownloadStatus.STATE_ERR_CONN,-1);
                    e.printStackTrace();
                } finally {
                    conn.disconnect();
                }
            } else {
                Util.log("下载文件网络连接获取失败（"+fileUrl+"）");
                DownloadManager.getInstance().notifyDownloadState(uid,bid,DownloadStatus.STATE_ERR_CONN,-1);
            }
            // 记录结束时间
            long endTime=System.currentTimeMillis();
            Util.log("文件下载线程执行完毕（大小："+totalLength+"字节，耗时："+(endTime-startTime)+"毫秒，平均速度："+(totalLength*1000/(endTime-startTime))+"字节/秒"+fileUrl+"）>>>");
            // 删除映射表中线程记录
            DownloadManager.getInstance().deleteFileMap(uid+"_"+bid);
        }
    }
    
    /**
     * 更新文件下载状态
     */
    @Override
    public synchronized void updateDownState(int offset) {
        downloadInfo.setDownLength(downloadInfo.getDownLength()+offset);
        float downPercent=Util.getPercent(downloadInfo.getDownLength(), totalLength);
        long downTime2=System.currentTimeMillis();
        if((progressType==0&&(downPercent-downloadInfo.getDownloadPercent())>=progressUnit)
                ||(progressType==1&&((downTime2-downTime)>=progressUnit))
                ||downloadInfo.getDownLength()>=totalLength
                ) {
            // 下载完成但解压未完成前进度设置为99.99%
            downloadInfo.setDownloadPercent((downPercent==100)?99.99f:downPercent);
            downTime=downTime2;
            DownloadManager.getInstance().notifyDownloadState(uid, bid, downloadInfo.getDownloadStatus(), downloadInfo.getDownloadPercent());
        }
    }

    /**
     * 停止下载线程
     */
    @Override
    public void stop() {
        isPaused=true;
        if(pool!=null&&!pool.isTerminated()) {
            pool.shutdownNow();
            Util.log("停止下载线程");
        }
    }
}